www.gusucode.com > VC++写的C编译器源代码附设计文档-源码程序 > VC++写的C编译器源代码附设计文档-源码程序/code/C- Compiler/PCodeGrammar.cpp

    //	P-Code syntax used for coloring in CPCodeView
//                                      by 陆晓春
////////////////////////////////////////////////////////////////
// Download by http://www.NewXing.com
#include "stdafx.h"
#include "PCodeView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//C- key words
static LPTSTR s_apszPKeywordList[] =
{
	_T("global"),
	_T("local"),
	_T("param"),

	_T("lda"),	// 取变量地址
	_T("lod"),	// 取变量值
	_T("ldci"),	// 取int类型常数
	_T("ldcf"),	// 取float类型常数
	_T("ldcc"),	// 取char类型常数
	_T("ldc"),	// 取bool类型常数
	_T("fjp"),	// 错误跳跃
	_T("tjp"),	// 正确跳跃
	_T("ujp"),	// 无条件跳跃
	_T("stn"),	// 存储并保留值
	_T("sto"),	// 存储不保留值
	_T("ind"),	// 根据堆栈上的地址取值
	_T("ixa"),	// 根据堆栈上的地址取地址
	_T("adi"),	// int类型加法
	_T("adr"),	// float类型加法
	_T("sbi"),	// int类型减法
	_T("sbr"),	// float类型减法
	_T("mpi"),	// int类型乘法
	_T("mpr"),	// float类型乘法
	_T("dvi"),	// int类型除法
	_T("dvr"),	// float类型除法
	_T("mod"),	// %运算
	_T("grt"),	// >运算
	_T("les"),	// <运算
	_T("geq"),	// >=运算
	_T("leq"),	// <=运算
	_T("equ"),	// ==运算
	_T("not"),	// !运算
	_T("neq"),	// !=运算
	_T("and"),	// 逻辑与运算
	_T("or"),	// 逻辑或运算
	_T("mst"),	// 标志函数调用的参数的开始
	_T("ent"),	// 函数定义开始
	_T("ret"),	// 函数返回
	_T("cup"),	// 调用函数
	_T("lab"),	// 标号
	_T("rdi"),	// 从标准输入读入一个整数存到栈顶的地址(并pop栈顶的地址)
	_T("rdc"),	// 从标准输入读入一个字符存到栈顶的地址(并pop栈顶的地址)
	_T("rdf"),	// 从标准输入读入一个浮点数存到栈顶的地址(并pop栈顶的地址)
	_T("wri"),	// 把栈顶的一个整数送到标准输出(并pop栈顶的整数)
	_T("wrc"),	// 把栈顶的一个字符送到标准输出(并pop栈顶的字符)
	_T("wrf"),	// 把栈顶的一个浮点数送到标准输出(并pop栈顶的浮点数)
	
	_T("elem_size"),

	NULL
};

static BOOL IsPKeyword(LPCTSTR pszChars, int nLength)
{
	char* tmp = strdup( pszChars );
	for( unsigned int i=0; i < strlen(tmp); i++ )
		tmp[i] = tolower(tmp[i]);
	for( int L = 0; s_apszPKeywordList[L] != NULL; L++ ) {
		if( strncmp(s_apszPKeywordList[L], tmp, nLength) == 0 &&
			s_apszPKeywordList[L][nLength] == 0 ) {
			delete tmp;
			return TRUE;
		}
	}

	delete tmp;
	return FALSE;
}

static BOOL IsPNumber(LPCTSTR pszChars, int nLength)
{
	if( nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x' ) {
		for( int I = 2; I < nLength; I++ ) {
			if (isdigit(pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
										(pszChars[I] >= 'a' && pszChars[I] <= 'f'))
				continue;
			return FALSE;
		}
		return TRUE;
	}
	if( !isdigit(pszChars[0]) ) return FALSE;
	for( int I = 1; I < nLength; I++ ) {
		if( !isdigit(pszChars[I]) && pszChars[I] != '+' &&
			pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
			pszChars[I] != 'E' )
			return FALSE;
	}
	return TRUE;
}

#define DEFINE_BLOCK(pos, colorindex)	\
	ASSERT((pos) >= 0 && (pos) <= nLength);\
	if (pBuf != NULL)\
	{\
		if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
		pBuf[nActualItems].m_nCharPos = (pos);\
		pBuf[nActualItems].m_nColorIndex = (colorindex);\
		nActualItems ++;}\
	}

#define COOKIE_COMMENT			0x0001
#define COOKIE_PREPROCESSOR		0x0002
#define COOKIE_EXT_COMMENT		0x0004
#define COOKIE_STRING			0x0008
#define COOKIE_CHAR				0x0010

DWORD CPCodeView::ParseLine(DWORD dwCookie, int nLineIndex, TEXTBLOCK *pBuf, int &nActualItems)
{
	int nLength = GetLineLength( nLineIndex );
	if( nLength <= 0 )
		return dwCookie & COOKIE_EXT_COMMENT;

	LPCTSTR pszChars    = GetLineChars(nLineIndex);
	BOOL bFirstChar     = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
	BOOL bRedefineBlock = TRUE;
	BOOL bDecIndex  = FALSE;
	int nIdentBegin = -1;
	for( int I = 0; ; I++ ) {
		if( bRedefineBlock ) {
			int nPos = I;
			if( bDecIndex )	nPos--;
			if( dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT) ) {
				DEFINE_BLOCK(nPos, COLORINDEX_COMMENT);
			} else if( dwCookie & (COOKIE_CHAR | COOKIE_STRING) ) {
				DEFINE_BLOCK(nPos, COLORINDEX_STRING);
			} else if( dwCookie & COOKIE_PREPROCESSOR )	{
				DEFINE_BLOCK(nPos, COLORINDEX_PREPROCESSOR);
			} else {
				DEFINE_BLOCK(nPos, COLORINDEX_NORMALTEXT);
			}
			bRedefineBlock = FALSE;
			bDecIndex      = FALSE;
		}

		if( I == nLength ) break;

		if( dwCookie & COOKIE_COMMENT ) {
			DEFINE_BLOCK(I, COLORINDEX_COMMENT);
			dwCookie |= COOKIE_COMMENT;
			break;
		}

		// String constant "....", end
		if( dwCookie & COOKIE_STRING ) {
			if( pszChars[I] == '"' && (I == 0 || pszChars[I - 1] != '\\') )	{
				dwCookie &= ~COOKIE_STRING;
				bRedefineBlock = TRUE;
			}
			continue;
		}

		// Char constant '..', end
		if( dwCookie & COOKIE_CHAR ) {
			if( pszChars[I] == '\'' && (I == 0 ||
				(I >= 2 && pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\') ||
				pszChars[I - 1] != '\\') ) {
				dwCookie &= ~COOKIE_CHAR;
				bRedefineBlock = TRUE;
			}
			continue;
		}

		// Extended comment /*....*/, end
		if( dwCookie & COOKIE_EXT_COMMENT ) {
			if( I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '*' ) {
				dwCookie &= ~COOKIE_EXT_COMMENT;
				bRedefineBlock = TRUE;
			}
			continue;
		}

		// Comment double slash //
		if( I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '/' ) {
			DEFINE_BLOCK(I - 1, COLORINDEX_COMMENT);
			dwCookie |= COOKIE_COMMENT;
			break;
		}
		
		// Comment semicolon
		if( pszChars[I] == ';' ) {
			DEFINE_BLOCK(I, COLORINDEX_COMMENT);
			dwCookie |= COOKIE_COMMENT;
			break;
		}

		// Preprocessor directive #....
		if( dwCookie & COOKIE_PREPROCESSOR ) {
			/*if( I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/') {
				DEFINE_BLOCK(I - 1, COLORINDEX_COMMENT);
				dwCookie |= COOKIE_EXT_COMMENT;
			}*/
			if( !isalpha(pszChars[I]) ) {
				dwCookie &= ~COOKIE_PREPROCESSOR;
				bRedefineBlock = TRUE;
			}
			continue;
		}

		// String constant "...."
		if( pszChars[I] == '"') {
			DEFINE_BLOCK(I, COLORINDEX_STRING);
			dwCookie |= COOKIE_STRING;
			continue;
		}

		// Char constant '..'
		if( pszChars[I] == '\'' ) {
			DEFINE_BLOCK(I, COLORINDEX_STRING);
			dwCookie |= COOKIE_CHAR;
			continue;
		}

		// Extended comment /*....*/
		if( I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/' ) {
			DEFINE_BLOCK(I - 1, COLORINDEX_COMMENT);
			dwCookie |= COOKIE_EXT_COMMENT;
			continue;
		}

		if( bFirstChar ) {
			if( pszChars[I] == '#' ) {
				DEFINE_BLOCK(I, COLORINDEX_PREPROCESSOR);
				dwCookie |= COOKIE_PREPROCESSOR;
				continue;
			}
			if( !isspace(pszChars[I]) )
				bFirstChar = FALSE;
		}

		if( pBuf == NULL )
			continue;	//	We don't need to extract keywords,
						//	for faster parsing skip the rest of loop

		// Operators
		if( pszChars[I] == '+' || pszChars[I] == '-' || pszChars[I] == '=' || 
			pszChars[I] == '<' || pszChars[I] == '>' || pszChars[I] == '!' ||
			pszChars[I] == '|' || pszChars[I] == '&' || pszChars[I] == '^' ) {
			DEFINE_BLOCK(I, COLORINDEX_OPERATOR);
			bRedefineBlock = TRUE;
			continue;
		}

		if( pszChars[I] == '*' ||
			(pszChars[I] == '/' && (I < (nLength - 1) && pszChars[I + 1] != '/' && pszChars[I + 1] != '*')) ) {
			DEFINE_BLOCK(I, COLORINDEX_OPERATOR);
			bRedefineBlock = TRUE;
			continue;
		}

		if( isalnum(pszChars[I]) || pszChars[I] == '_' || pszChars[I] == '.' ) {
			if (nIdentBegin == -1) nIdentBegin = I;
		} else {
			if( nIdentBegin >= 0 ) {
				if( IsPKeyword(pszChars + nIdentBegin, I - nIdentBegin) ) {
					DEFINE_BLOCK(nIdentBegin, COLORINDEX_KEYWORD);
				} else if( IsPNumber(pszChars + nIdentBegin, I - nIdentBegin) ) {
					DEFINE_BLOCK(nIdentBegin, COLORINDEX_NUMBER);
				}
				bRedefineBlock = TRUE;
				bDecIndex = TRUE;
				nIdentBegin = -1;
			}
		}
	}

	if( nIdentBegin >= 0 ) {
		if( IsPKeyword(pszChars + nIdentBegin, I - nIdentBegin)) {
			DEFINE_BLOCK(nIdentBegin, COLORINDEX_KEYWORD);
		} else if( IsPNumber(pszChars + nIdentBegin, I - nIdentBegin) ) {
			DEFINE_BLOCK(nIdentBegin, COLORINDEX_NUMBER);
		}
	}

	if( pszChars[nLength - 1] != '\\' )	dwCookie &= COOKIE_EXT_COMMENT;

	return dwCookie;
}